# 2.5 任务、函数及预处理 ## 任务 `task` 1. 定义格式 ```verilog task ; // 注意无端口列表 // 端口和数据类型声明语句; // 其他语句; endtask ``` 2. 调用格式 ```verilog (port1, port2, ......); ``` 3. 注意事项 1. 任务调用时和定义时的端口变量应是一一对应的。 2. 任务的定义与调用须在一个`module`模块内。定义任务时,没有端口名列表,但需要紧接着进行输入输出端口和数据类型的说明。 3. 任务在被调用时激活。任务调用与模块调用一样通过任务名调用实现,调用时,需列出端口名列表,端口名的排序和类型必须与任务定义中的相一致。 4. 一个任务可调用别的任务和函数,可调用的任务和函数个数不限。 ## 函数 `function` 1. 定义格式 ```verilog function <...> function_name; // ... 表示返回值位宽或类型说明 // 端口声明; // 局部变量定义; // 其他语句; endfunction ``` 2. 注意事项 1. `<返回值位宽或类型说明>`是一个可选项,如果缺省,则返回值为1位寄存器类型的数据。 2. 函数的定义与调用须在一个`module`模块内。 3. 函数只允许有输入变量且必须至少有一个输入变量,输出变量由函数名本身担任,在定义函数时,需对函数名说明其类型和位宽。 4. 定义函数时,没有端口名列表,但调用函数时,需列出端口名列表,端口名的排序和类型必须与定义时的相一致。这一点与任务相同。 5. 函数可以出现在持续赋值`assign`的右端表达式中。 6. 函数不能调用任务,而任务可以调用别的任务和函数,且调用任务/函数个数不受限制。 ## 任务与函数的比较 | **比较项目** | **任务** | **函数** | |-------------|----------|----------| | 输入与输出 | 可有任意个各种类型的参数 | 至少有一个输入,不能将`inout`类型作为输出 | | 调用方式 | 只能在过程语句中调用,不能在连续赋值语句`assign`中调用 | 函数可作为表达式中的一个操作数来调用,在过程赋值和连续赋值语句中均可以调用 | | 定时事件控制 | 支持 | 不支持 | | 调用其他任务和函数 | 支持 | 可调用其他函数,不能调用其他任务 | | 返回值 | 不支持 | 支持 | ## 编译预处理语句 Verilog允许在程序中使用特殊的编译向导(Compiler Directives)语句,在编译时,通常先对这些向导语句进行"预处理",然后再将预处理的结果和源程序一起进行编译。向导语句以符号`` ` ``开头,以区别于其它语句。比较常用的有`` `define``,`` `include``和`` `ifdef``、`` `else``、`` `endif``等。 1. `` `define``语句 用于将一个简单的名字或标志符(或称为宏名)来代替一个复杂的名字或字符串。 ```verilog `define ``` 2. `` `include``语句 文件包含语句,用于将一个文件全部包含到另一个文件中。 ```verilog `include "filename" ``` 1. 一个`` `include``语句只能指定一个被包含的文件。 2. `` `include``语句可以出现在源程序的任何地方。被包含的文件若与包含文件不在同一个子目录下,必须指明其路径名。 3. 文件包含允许多重包含,比如文件1包含文件2,文件2又包含文件3等。